#--------------- Loli Pan-ic -------------------------------------------------//
#------------ Created by Hebiko ----------------------------------------------//

from pygame import *
from pygame import gfxdraw
import textwrap
import MenuSystem
import random
import sys
from os.path import dirname,join

import lolipan_rngdata as lolirng

# GLOBALS ---------------------------------------------------------------------

# Event Globals
MAINTICK = USEREVENT + 1

# Screen Globals
SCR_X, SCR_Y = 800, 600 #Screen X and Y
scr = display.set_mode([SCR_X,SCR_Y])
display.flip()

# Menu Booleans
MENU_RSRC_DISPLAY = False

# Initialize MenuSystem with example settings
MenuSystem.init()
MenuSystem.BGCOLOR = Color(50,50,50,255)
MenuSystem.FGCOLOR = Color(200,200,200,255)
MenuSystem.BGHIGHTLIGHT = Color(0,0,0,255)
MenuSystem.BORDER_HL = Color(200,200,200,180)
#mn_bar = MenuSystem.MenuBar()
mn_bt1 = MenuSystem.Button('Exit',50,20)
mn_bt1.topleft = SCR_X-50, 0
mn_bt1.set()
mn_bt2 = MenuSystem.Button('About',50,20)
mn_bt2.topleft = 0, 0
mn_bt2.set()
mn_bt3 = MenuSystem.Button('Resources',80,20)
mn_bt3.topleft = 51, 0
mn_bt3.set(type=MenuSystem.SWITCH,switchlabel='Resources')

# Message Log Globals
mlog_disp = display.get_surface()
mlog_disp_rect = mlog_disp.get_rect()
mlog_bgcolor = Color(80,80,80,100)    
mlog_rect = Rect(5,20,(SCR_X/1.5)-5,SCR_Y-20)
mlog_bg = mlog_disp.subsurface(mlog_rect).copy()
ML_FONT = font.Font(join(dirname(__file__),"Roboto-Regular.ttf"),13)
mlog_lineheight = ML_FONT.get_height()
ML_HISTORY = []

# Loli List Globals
llist_bgcolor = Color(40, 40, 80, 150)
llist_rect = Rect((SCR_X/1.5) + 2, 20, (SCR_X-(SCR_X/1.5))-4, SCR_Y-20)
llist_bg = mlog_disp.subsurface(llist_rect).copy()
LL_FONT = font.Font(join(dirname(__file__),"Roboto-Regular.ttf"),12)
llist_lineheight = LL_FONT.get_height()
LOLI_LIST = []

# Database Globals
RESRC_DB = []
RESEARCH_DB = []
UPG_DB = []

# CLASSES ---------------------------------------------------------------------

class Loli_Base:
    def __init__(self, entryname, pers):
        self.attDict = {'hp':1,'str':1,'int':1,'dex':1,'agi':1,'obed':1,'fear':1,'lrn':1}
        self.entryname = entryname
        self.descDict = {'haircolor':'','hairstyle':'','skintone':'','eyecolor1':'','eyecolor2':''}
        self.personality = pers
        self.loli_ident = random.randint(1,99999999)
        self.events = []
        self.queue = []
        self.activity = 'idle'
    
class Tick_Event:
    def __init__(self, entryname, length, loli_link=None, func=None, mess=None, params=None):
        self.entryname = entryname
        self.eventFunc = func
        self.eventMess = mess
        self.eventLength = length
        self.loli_link = loli_link
        self.params = params
        
    def callFunc(self):
        if self.eventMess is not None:
            if self.loli_link is not None:
                place_name = self.eventMess.replace('loliName',getLoliName(self.loli_link))
                new_mess(place_name,Color(50,125,50,255))
            else:
                new_mess(self.eventMess,Color(50,125,50,255))
        if self.eventFunc is not None:
            funcCall = self.eventFunc
            if self.params is not None:
                returnVal = funcCall(self.params)
            else:
                returnVal = funcCall()
            return returnVal
        else:
            return None
        
class Resource:
    def __init__(self, entryname, maxVal):
        self.entryname = entryname
        self.value = 0
        self.maxValue = maxVal
        
    def increm(self, amount):
        if self.value < self.maxValue:
            self.value += amount
        else:
            self.value = self.maxValue
            
    def decrem(self, amount):
        if self.value > 0:
            self.value -= amount
        else:
            self.value = 0
            
class Research:
    def __init__(self, entryname, time, upgradeUlock=None):
        self.entryname = entryname
        self.time = time
        self.upgradeUlock = upgradeUlock
        
    def activate(self):
        if self.upgradeUlock is not None:
            returnVal = self.upgradeUlock.activate()
            if returnVal is not None:
                return returnVal
            else:
                return None
        
class Upgrade:
    def __init__(self, entryname, effect=None):
        self.entryname = entryname
        self.effect = effect
        
    def activate(self):
        if self.effect is not None:
            funcCall = self.effect
            returnVal = funcCall()
            return returnVal
        else:
            return None

# UI FUNCTIONS ----------------------------------------------------------------

def init_UI():
    #mn_file = MenuSystem.Menu('File', ['Exit'])
    #mn_help = MenuSystem.Menu('Help', ['About'])    
    #mn_bar.set((mn_file,mn_help))
    #display.update(mn_bar)
    
    # Time to render the Message Log...     
    mlog_disp.blit(mlog_bg,mlog_rect)
    gfxdraw.box(mlog_disp,mlog_rect,mlog_bgcolor)
    
    # Time to render the Loli List...
    mlog_disp.blit(llist_bg,llist_rect)
    gfxdraw.box(mlog_disp,llist_rect,llist_bgcolor)
    
    # Initialize main tick event as a timer (4 seconds)
    time.set_timer(MAINTICK,3000)
    
def new_mess(text, color = Color(255,255,255,255)):
    tw_lines = textwrap.wrap(text,90)
    for line in tw_lines:
        if len(ML_HISTORY) == (34):
            del ML_HISTORY[0]
        ML_HISTORY.append((line,color))
    update_mlog()
        
def update_mlog():
    mlog_disp.blit(mlog_bg,mlog_rect)
    gfxdraw.box(mlog_disp,mlog_rect,mlog_bgcolor)    
    #display.update(mlog_rect)
    y = mlog_rect.y
    x = mlog_rect.x + mlog_lineheight/3
    for (line, color) in ML_HISTORY:
        mlog_disp.blit(ML_FONT.render(line,1,color),(x,y)).right+mlog_lineheight
        y += mlog_lineheight
    #display.update(mlog_rect)
    
def update_llist():
    mlog_disp.blit(llist_bg,llist_rect)
    gfxdraw.box(mlog_disp,llist_rect,llist_bgcolor)
    y = llist_rect.y
    x = llist_rect.x + llist_lineheight/3
    for entry in LOLI_LIST:
        loli_name = entry.entryname
        loli_act = entry.activity
        disp_line = str(entry.entryname)+' - '+str(entry.activity.capitalize())
        mlog_disp.blit(LL_FONT.render(disp_line,1,Color(200,200,200,255)),(x,y)).right+llist_lineheight
        y += llist_lineheight
        
def show_rsrc_list():
    rsrcdisp = display.get_surface()
    rsrc_disp_rect = rsrcdisp.get_rect()
    rsrc_bgcolor = Color(10,10,10,255)
    rsrc_listlength = len(RESRC_DB)
    rsrc_rect = Rect((SCR_X/2.5),(SCR_Y/2.5),150,rsrc_listlength*14)
    rsrc_bg = rsrcdisp.subsurface(rsrc_rect).copy()
    rsrc_FONT = font.Font(join(dirname(__file__),"Roboto-Regular.ttf"),13)
    rsrc_lineheight = rsrc_FONT.get_height() - 5
    # --
    rsrcdisp.blit(rsrc_bg,rsrc_rect)
    gfxdraw.box(rsrcdisp,rsrc_rect,rsrc_bgcolor)
    y = rsrc_rect.y
    x = rsrc_rect.x + rsrc_lineheight/3
    for resource in RESRC_DB:
        display_line = str(resource.entryname.capitalize()) + ' - ' + str(resource.value)
        rsrcdisp.blit(rsrc_FONT.render(display_line,1,Color(200,200,200,255)),(x,y)).right+rsrc_lineheight
        y += rsrc_lineheight
        
def redraw_all():
    update_mlog()
    update_llist()
        
# MAIN TICK FUNCTIONS ---------------------------------------------------------
        
def tickEvents():
    for loli in LOLI_LIST:
        for event in loli.events:
            if event.eventLength > 0:
                event.eventLength += -1
            else:
                event.callFunc()
                eventInd = loli.index(event) if event in loli.events else None
                if eventInd is not None:
                    del loli.events[eventInd]
                
def newLoliEvent():
    for loli in LOLI_LIST:
        if loli.activity == 'idle':
            new_event = lolirng.choose_event()
            event_name, event_messages, effects, length = new_event[0], new_event[1], new_event[2], new_event[3]
            loli_str = loli.attDict['str']
            event_action, func_type, rsrc_min, rsrc_max, rsrc_type = None, None, None, None, None
            if effects is not 'none':
                if effects == 'inc_wood':
                    func_type = 'rsrc_add'
                    rsrc_min, rsrc_max = loli_str+1, loli_str+random.randint(2,15)
                    rsrc_type = 'wood'
                    #event_action = add_rsrc('wood',random.randint(rsrc_min,rsrc_max))
                elif effects == 'inc_stone':
                    func_type = 'rsrc_add'
                    rsrc_min, rsrc_max = loli_str+1, loli_str+random.randint(2,15)
                    rsrc_type = 'stone'
                    #event_action = add_rsrc('stone',random.randint(rsrc_min,rsrc_max))
                elif effects == 'inc_flint':
                    func_type = 'rsrc_add'
                    rsrc_min, rsrc_max = loli_str+1, loli_str+random.randint(2,15)
                    rsrc_type = 'flint'
                    #event_action = add_rsrc('flint',random.randint(rsrc_min,rsrc_max))
                elif effects == 'inc_clay':
                    func_type = 'rsrc_add'
                    rsrc_min, rsrc_max = loli_str+1, loli_str+random.randint(2,15)
                    rsrc_type = 'clay'
                    #event_action = add_rsrc('clay',random.randint(rsrc_min,rsrc_max))
            else: func_type = 'none'
            
            if func_type == 'rsrc_add':
                loli.events.append(Tick_Event(event_name,length,loli_link=loli.loli_ident,func=add_rsrc,mess=random.choice(event_messages),params=(rsrc_type,random.randint(rsrc_min,rsrc_max))))
                loli.activity = event_name
            elif func_type == 'none':                
                loli.events.append(Tick_Event(event_name,length,loli_link=loli.loli_ident,mess=random.choice(event_messages)))
                loli.activity = event_name
            
    
def hitTick():
    new_mess('*tick*',Color(80,80,80,150))
    newLoliEvent()
    update_llist()
    tickEvents()
    
# CLASS CREATION FUNCTIONS ----------------------------------------------------

def new_resource(data):
    name, maxVal = data[0], data[1]
    RESRC_DB.append(Resource(name,maxVal))
    
def new_upgrade(data):
    name, effect = data[0], data[1]
    UPG_DB.append(Upgrade(name,effect))
    
def new_research(data):
    name, time, uulock = data[0], data[1], data[2]
    RESEARCH_DB.append(Research(name, time, uulock))
    
def new_loli(data):
    name, personality = data[0], data[1]
    LOLI_LIST.append(Loli_Base(name,personality))
    
def load_gamedata():
    for entries in lolirng.rsrc_list:
        new_resource(entries)
    
# EVENT-CALLED FUNCTIONS AND MISC ---------------------------------------------
    
def testFunc():
    new_mess('Called test function successfully.',Color(0,255,0,255))
    random_rsrc = random.choice(RESRC_DB)
    random_rsrc.increm(500)
    new_mess('Added 500 to '+str(random_rsrc.entryname.capitalize()))
    
def loc_rsrc(search):
    for entry in RESRC_DB:
        if entry.entryname.lower() == search.lower():
            return entry
    else:
        return None
    
def add_rsrc(tupl):
    rsrc, num = tupl[0], tupl[1]
    f_rsrc = loc_rsrc(rsrc)
    if f_rsrc is not None:
        f_rsrc.increm(num)
    else:
        return False
    
def getLoliName(ident):
    for lolis in LOLI_LIST:
        if lolis.loli_ident == ident:
            return lolis.entryname
        
def getLoli(ident):
    for lolis in LOLI_LIST:
        if lolis.loli_ident == ident:
            return lolis

# STARTUP FUNCTIONS
init_UI()
load_gamedata()
hitTick()
new_loli(('Imouto','littlesis'))
update_llist()
#EVENT_QUEUE.append(Tick_Event(2,func=testFunc))
new_mess('Welcome to Loli Pan-ic!',Color(0,128,255,255))

while True:
    #ev = event.wait()
    if event.get(MAINTICK):
        hitTick()
    elif event.get(QUIT):
        quit()
        sys.exit()
    
    for ev in event.get():
        if mn_bt1.update(ev):
            if mn_bt1.clicked: 
                quit()
                sys.exit()
        if mn_bt2.update(ev):
            if mn_bt2.clicked:
                new_mess('Insert about message or whatever here.',Color(255,0,0,255))
        if mn_bt3.update(ev):
            if mn_bt3.clicked:
                if MENU_RSRC_DISPLAY == False:
                    MENU_RSRC_DISPLAY = True
                else:
                    redraw_all()
                    MENU_RSRC_DISPLAY = False
        #display.update(mn_bar.update(ev))
        
    if MENU_RSRC_DISPLAY == True:
        show_rsrc_list()
    #if mn_bar.choice:
        #print(mn_bar.choice)
        #print(mn_bar.choice_label)
        #print(mn_bar.choice_index)
        #if mn_bar.choice_label[1] == 'Exit': break
        #elif mn_bar.choice_label[1] == 'About':
            #new_mess('About test derpderp')
            #mn_bar.choice = None
        
    display.flip()            